在上一篇《Activiti使用之–零配置实现spring集成activiti》中,介绍了如何通过spring注解的方式,实例化activit的流程引擎。 在本篇中,将介绍在多数据库的需求场景下,要求每个数据库,都需要有流程引擎的业务。因此需要对每个数据库都进行activit的初始化;在业务代码中,使用注解+AOP技术实现数据库的动态切换(动态数据源这里不做介绍),在多数据源的基础上,activiti的初始代码如下:
import com.tian.plugin.mybatis.config.MybatisConfig;
import com.tian.plugin.mybatis.prop.DataSourceVo;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.*;
import org.activiti.spring.ProcessEngineFactoryBean;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.util.Map;
import java.util.Set;
/**
* Copyright: Copyright (c) 2019 xxx有限公司
*
* @ClassName: ActivitiConfigAware
* @Description: Activiti流程引擎的注册及初始化
* @version: v1.0.0
* @author: tblong
* @date: 2020/2/17 14:52
*
* Modification History:
* Date Author Version Description
* -------------------------------------------------------------*
* 2020/2/17 tblong v1.0.0 新建
*/
@Slf4j
@Component
public class ActivitiConfigAware implements BeanFactoryAware, InitializingBean, ApplicationContextAware {
private DefaultListableBeanFactory beanFactory;
private ApplicationContext applicationContext;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (DefaultListableBeanFactory) beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void afterPropertiesSet() throws Exception {
log.debug("----------------------> ActivitiConfigAware init......");
//获取全部数据源,然后将单个数据源,分别注册到Spring IOC容器中管理;
MybatisConfig mybatisConfig = (MybatisConfig) applicationContext.getBean("mybatisConfig");
Map dsMap = mybatisConfig.getDataSourceMap();
for(Map.Entry map : dsMap.entrySet()){
String dataNode = (String) map.getKey();
DataSource dataSource = (DataSource) map.getValue();
log.debug("------------->dataNode=" + dataNode);
if(dataNode != null && !"".equals(dataNode) && !DataSourceVo.PMS_DEFAULT_DATABASE_NODE.equals(dataNode)){
//注册数据源
registerDataSource(dataNode, dataSource);
//注册事务管理器
registerTransactionManager(dataNode);
//注册流程引擎
registerActivitiEngineConfigureation(dataNode);
//注册流程引擎工厂Bean
registerProcessEngineFactoryBean(dataNode);
//注册流程引擎5大服务
registerActivitiService(dataNode);
}
}
}
private void registerDataSource(String nodeNo, DataSource dataSource){
String beanName = "dataSource_" + nodeNo;
beanFactory.registerSingleton(beanName, dataSource);
}
private void registerTransactionManager(String nodeNo){
String beanName = "transactionManager_" + nodeNo;
DataSource dataSource = (DataSource) applicationContext.getBean("dataSource_" + nodeNo);
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
beanFactory.registerSingleton(beanName, transactionManager);
}
private void registerActivitiEngineConfigureation(String nodeNo){
String beanName = "activitiEngineConfigureation_" + nodeNo;
DataSource dataSource = (DataSource) applicationContext.getBean("dataSource_" + nodeNo);
DataSourceTransactionManager transactionManager = (DataSourceTransactionManager) applicationContext.getBean("transactionManager_" + nodeNo);
SpringProcessEngineConfiguration processEngineConfiguration = new SpringProcessEngineConfiguration();
//设置数据源
processEngineConfiguration.setDataSource(dataSource);
//设置事务管理器
processEngineConfiguration.setTransactionManager(transactionManager);
//自动创建流程引擎表
processEngineConfiguration.setDatabaseSchemaUpdate("false");
//是否激活Activiti的任务调度
processEngineConfiguration.setJobExecutorActivate(false);
//数据库类型
processEngineConfiguration.setDatabaseType("mysql");
processEngineConfiguration.setActivityFontName("宋体");
processEngineConfiguration.setLabelFontName("宋体");
processEngineConfiguration.setXmlEncoding("UTF-8");
//如果不需要刷流程图到引擎表,请注释掉下面这行。需要则放开注释
//configBeanDefinitionBuilder.addPropertyValue("deploymentResources", "classpath:com/pas/cloud/activiti/yjsp/*.bpmn");
beanFactory.registerSingleton(beanName, processEngineConfiguration);
}
private void registerProcessEngineFactoryBean(String nodeNo){
String beanName = "processEngineFactoryBean_" + nodeNo;
SpringProcessEngineConfiguration springProcessEngineConfiguration = (SpringProcessEngineConfiguration) applicationContext.getBean("activitiEngineConfigureation_" + nodeNo);
ProcessEngineFactoryBean processEngineFactoryBean = new ProcessEngineFactoryBean();
processEngineFactoryBean.setProcessEngineConfiguration(springProcessEngineConfiguration);
beanFactory.registerSingleton(beanName, processEngineFactoryBean);
}
private void registerActivitiService(String nodeNo){
ProcessEngineImpl processEngine = (ProcessEngineImpl) applicationContext.getBean("processEngineFactoryBean_" + nodeNo);
if(processEngine != null){
RepositoryService repositoryService = processEngine.getRepositoryService();
beanFactory.registerSingleton("repositoryService_" + nodeNo, repositoryService);
IdentityService identityService = processEngine.getIdentityService();
beanFactory.registerSingleton("identityService_" + nodeNo, identityService);
RuntimeService runtimeService = processEngine.getRuntimeService();
beanFactory.registerSingleton("runtimeService_" + nodeNo, runtimeService);
TaskService taskService = processEngine.getTaskService();
beanFactory.registerSingleton("taskService_" + nodeNo, taskService);
HistoryService historyService = processEngine.getHistoryService();
beanFactory.registerSingleton("historyService_" + nodeNo, historyService);
}else{
log.error("Activiti ProcessEngine is null......");
}
}
}
通过以上代码,对每个数据源,都进行了activiti的初始化。在业务代码使用时,需要动态的从IOC容器中,获取对应的activiti实例进行使用; 如下面代码,根据数据节点db,动态的从spring容器中,获取taskservice、runtimeservice的bean实例,处理对应数据库中的流程数据。
@Service
public class AcmtActivitiServiceImpl {
@Resource
private ApplicationContext applicationContext;
/**
* 改变当前流程节点状态 通过或者不通过
* @param taskid 任务ID
* @param completeFalg 状态 true为通过 false为不通过
* @return 业务ID
* @author tblong
*/
@Override
public String updateTaskCompleteStatus(String taskid, String userid, String completeFalg, String db) {
if(db == null || "".equals(db)){
log.error("数据库节点错误!");
throw new MultiDataSourceException(ErrorCode.Db_Node_Error);
}
taskservice = (TaskServiceImpl) applicationContext.getBean("taskService_" + db);
if(taskservice != null){
Task task=taskservice.createTaskQuery().taskId(taskid).singleResult();
String instanceid=task.getProcessInstanceId();
runtimeservice = (RuntimeServiceImpl) applicationContext.getBean("runtimeService_" + db);
if(runtimeservice != null){
ProcessInstance ins=runtimeservice.createProcessInstanceQuery().processInstanceId(instanceid).singleResult();
Map variables=new HashMap();
variables.put("pass", completeFalg);
taskservice.claim(taskid, userid);
taskservice.complete(taskid,variables);
return ins.getBusinessKey();
}
}
return null;
}
}
|